﻿using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace EWSEditor.CRM
{
    /// <summary>
    /// The ExchangeSyncStateXml object does not initialize the ExchangeFolderSyncState.
    /// This has been decoupled for performance reasons. If you need ExchangeFolderSyncState,
    /// you can call it via it's own constructor.
    /// </summary>
    public class ExchangeSyncStateXml
    {

        public DateTime LastSyncItemRetrievedTime
        {
            get { return _lastSyncItemRetrievedTime; }
        }
        private DateTime _lastSyncItemRetrievedTime;

        public DateTime LastSyncStartTime
        {
            get { return _lastSyncStartTime; }
        }

        private DateTime _lastSyncStartTime;

        public DateTime LastSyncEndTime
        {
            get { return _lastSyncEndTime; }
        }

        private DateTime _lastSyncEndTime;

        public int LastSyncDataProviderChangeCount
        {
            get { return _lastSyncDataProviderChangeCount; }
        }

        private int _lastSyncDataProviderChangeCount;

        public int LastSyncExchangeItemFinderChangeCount
        {
            get { return _lastSyncExchangeItemFinderChangeCount; }
        }

        private int _lastSyncExchangeItemFinderChangeCount;

        public int LastSyncExchangeItemFinderCreateChangeCount
        {
            get { return _lastSyncExchangeItemFinderCreateChangeCount; }
        }

        private int _lastSyncExchangeItemFinderCreateChangeCount;

        public int LastSyncExchangeItemFinderUpdateChangeCount
        {
            get { return _lastSyncExchangeItemFinderUpdateChangeCount; }
        }

        private int _lastSyncExchangeItemFinderUpdateChangeCount;

        public int LastSyncExchangeItemFinderDeleteChangeCount
        {
            get { return _lastSyncExchangeItemFinderDeleteChangeCount; }
        }

        private int _lastSyncExchangeItemFinderDeleteChangeCount;

        public int LastSyncCrmItemFinderChangeCount
        {
            get { return _lastSyncCrmItemFinderChangeCount; }
        }

        private int _lastSyncCrmItemFinderChangeCount;

        public int LastSyncCrmItemFinderCreateChangeCount
        {
            get { return _lastSyncCrmItemFinderChangeCount; }
        }

        private int _lastSyncCrmItemFinderCreateChangeCount;

        public int LastSyncCrmItemFinderUpdateChangeCount
        {
            get { return _lastSyncCrmItemFinderUpdateChangeCount; }
        }

        private int _lastSyncCrmItemFinderUpdateChangeCount;

        public int LastSyncCrmItemFinderDeleteChangeCount
        {
            get { return _lastSyncCrmItemFinderDeleteChangeCount; }
        }

        private int _lastSyncCrmItemFinderDeleteChangeCount;

        public Guid ClientId
        {
            get { return _clientId; }
        }

        private Guid _clientId;

        public Guid SubscriptionId
        {
            get { return _subscriptionId; }
        }

        private Guid _subscriptionId;

        public bool RebuildIdMapping
        {
            get { return _rebuildIdMapping; }
        }

        private bool _rebuildIdMapping;

        //public List<ExchangeFolderSyncState> LastFolderHierarchySyncStates
        //{
        //    get { return _lastFolderHierarchySyncStates; }
        //}

        //private List<ExchangeFolderSyncState> _lastFolderHierarchySyncStates;

        //public List<ExchangeFolderSyncState> LastFolderItemsSyncStates
        //{
        //    get { return _lastFolderItemsSyncStates; }
        //}

        //private List<ExchangeFolderSyncState> _lastFolderItemsSyncStates;


        public ExchangeSyncStateXml(string Xml)
        {
            if (String.IsNullOrEmpty(Xml))
            {
                throw new Exception("ExchangeSyncStateXml is null.");
            }

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(Xml);
            string xpath = "ExchangeSyncState";
            var nodes = doc.SelectNodes(xpath);
            SetProperties(nodes);
        }

        private void SetProperties(XmlNodeList nodes)
        {
            foreach (XmlNode node in nodes)
            {

                foreach (XmlNode node1 in node)
                {
                    switch (node1.Name)
                    {
                        case "LastSyncItemRetrievedTime":
                            _lastSyncItemRetrievedTime = Convert.ToDateTime(node1.InnerText, CultureInfo.InvariantCulture);

                            break;

                        case "LastSyncStartTime":
                            _lastSyncStartTime = Convert.ToDateTime(node1.InnerText, CultureInfo.InvariantCulture);
                            break;

                        case "LastSyncEndTime":
                            _lastSyncEndTime = Convert.ToDateTime(node1.InnerText, CultureInfo.InvariantCulture);
                            break;

                        case "LastSyncDataProviderChangeCount":
                            _lastSyncDataProviderChangeCount = Convert.ToInt32(node1.InnerText);
                            break;

                        case "LastSyncExchangeItemFinderChangeCount":
                            _lastSyncExchangeItemFinderChangeCount = Convert.ToInt32(node1.InnerText);
                            break;

                        case "LastSyncExchangeItemFinderCreateChangeCount":
                            _lastSyncExchangeItemFinderCreateChangeCount = Convert.ToInt32(node1.InnerText);
                            break;

                        case "LastSyncExchangeItemFinderUpdateChangeCount":
                            _lastSyncExchangeItemFinderUpdateChangeCount = Convert.ToInt32(node1.InnerText);
                            break;

                        case "LastSyncExchangeItemFinderDeleteChangeCount":
                            _lastSyncExchangeItemFinderDeleteChangeCount = Convert.ToInt32(node1.InnerText);
                            break;

                        case "LastSyncCrmItemFinderChangeCount":
                            _lastSyncCrmItemFinderChangeCount = Convert.ToInt32(node1.InnerText);
                            break;

                        case "LastSyncCrmItemFinderCreateChangeCount":
                            _lastSyncCrmItemFinderCreateChangeCount = Convert.ToInt32(node1.InnerText);
                            break;

                        case "LastSyncCrmItemFinderUpdateChangeCount":
                            _lastSyncCrmItemFinderUpdateChangeCount = Convert.ToInt32(node1.InnerText);
                            break;

                        case "LastSyncCrmItemFinderDeleteChangeCount":
                            _lastSyncCrmItemFinderDeleteChangeCount = Convert.ToInt32(node1.InnerText);
                            break;

                        case "ClientId":
                            _clientId = new Guid(node1.InnerText);
                            break;

                        case "SubscriptionId":
                            _subscriptionId = new Guid(node1.InnerText);
                            break;

                        case "RebuildIdMapping":
                            if (node1.Value == "true")
                            {
                                _rebuildIdMapping = true;
                            }
                            else
                            {
                                _rebuildIdMapping = false;
                            }
                            break;

                        //case "LastFolderHierarchySyncStates":
                        //    BuildFolderHierarchySyncStates(node.ChildNodes);
                        //    break;

                        //case "LastFolderItemsSyncStates":
                        //    BuildFolderItemsSyncStates(node.ChildNodes);
                        //    break;
                    }
                }
            }
        }

        /// <summary>
        /// Returns a collection of ExchangeFolderSyncStates from the ExchangeSyncStateXml provided by the caller.
        /// </summary>
        /// <param name="Xpath">XML XPath to the specified ExchangeFolderSyncState nodes</param>
        /// <returns></returns>
        internal static List<ExchangeFolderSyncState> GetExchangeFolderSyncStateCollectionFromXpath(string Xpath, string ExchangeSyncStateXml)
        {
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.LoadXml(ExchangeSyncStateXml);
            string FolderXpath = Xpath;
            var nodes = xmldoc.SelectNodes(FolderXpath);
            List<ExchangeFolderSyncState> ExchangeFolderSyncStates = GetSyncStateCollection(nodes);
            return ExchangeFolderSyncStates;

        }

        private static List<ExchangeFolderSyncState> GetSyncStateCollection(XmlNodeList nodes)
        {
            List<ExchangeFolderSyncState> syncStates = new List<ExchangeFolderSyncState>();

            foreach (XmlNode node in nodes)
            {
                foreach (XmlNode node1 in node)
                {
                    ExchangeFolderSyncState folder = new ExchangeFolderSyncState(node1);
                    syncStates.Add(folder);
                }
            }
            return syncStates;
        }

        public static string GetCurrentExchangeSyncStateXml()
        {
            QueryByAttribute query = new QueryByAttribute("mailbox");
            query.ColumnSet = new ColumnSet();
            query.ColumnSet.AddColumn("exchangesyncstatexml");
            query.Attributes.AddRange("emailaddress");
            query.Values.AddRange(CrmOrgMailboxCache.TargetMailboxEmailAddress);
            query.Attributes.AddRange("statecode");
            query.Values.AddRange(0);
            EntityCollection mailboxes = CrmAuthInfoFactory.GetOrgProxy().RetrieveMultiple(query);

            if (!mailboxes[0].Contains("exchangesyncstatexml"))
            {
                return null;
            }

            return (string)mailboxes[0]["exchangesyncstatexml"];
        }
    }
}
